<?php
/**
 *  💡 免责声明：本软件不得用于商业用途，仅做学习交流
 *  ⚠️ 权利声明：本软件由版权人提供产品技术支持
 *  📅 项目编号：NX2025-0135
 */
namespace App\Service\Trade;

use App\Models\CreditTrade;
use App\Models\TradingHall;
use App\Service\BaseService;
use App\Service\User\BeanAccountService;
use App\Service\User\WalletAccountService;
use Illuminate\Support\Facades\DB;

class TradeService extends BaseService
{
    public function sell($trading_hall_id, $amount, $user) //卖出
    {
        return DB::transaction(function () use ($trading_hall_id, $amount, $user) {
            $user_id = $user->id;
            $buy = TradingHall::query()
                ->lockForUpdate()
                ->where('status', 1)
                ->find($trading_hall_id);
            //TODO 判断豆子
            if (blank($buy)) {
                return [
                    'flag' => false,
                    'msg' => '该求购单已失效！',
                ];
            }
            if ($amount > bcsub($buy->amount, $buy->traded_quantity, 2)) {
                return [
                    'flag' => false,
                    'msg' => '超出求购者 求购数量！',
                ];
            }
            if ($user_id == $buy->user_id) {
                return [
                    'flag' => false,
                    'msg' => '不能出售给自己！',
                ];
            }
            $blance = BeanAccountService::make()->checkTheBalance($user_id);
            if ($blance < $amount) {
                return [
                    'flag' => false,
                    'msg' => 'KC通证余额不足！售出失败！',
                ];
            }

            $sell = TradingHall::query()->create([
                'user_id' => $user_id,
                'amount' => $amount,
                'price' => $buy->price,
                'type' => 2,
                'status' => 2,
            ]);
            $total = bcmul($amount, $buy->price, 2);
            $msg = sprintf('售出KC通证 数量:%s 单价:%s 共计:%s', $amount, $buy->price, $total);
            $msg2 = sprintf('求购KC通证成功 数量:%s 单价:%s 共计:%s', $amount, $buy->price, $total);
            BeanAccountService::make()->consumption($user_id, $amount, $msg, 4);
            WalletAccountService::make()->recharge($user_id, $total, $msg, 6);

            BeanAccountService::make()->recharge($buy->user_id, $amount, $msg2, 4);
            $this->completed($sell, $buy);
            if ($amount == bcsub($buy->amount, $buy->traded_quantity, 2)) {
                $buy->status = 2;
            }
            $buy->traded_quantity += $amount;
            $buy->save();
            return [
                'flag' => true,
                'msg' => '售出成功！',
            ];
        });
    }

    public function buy($user_id, $amount, $price) //买入
    {
        return DB::transaction(function () use ($user_id, $amount, $price) {
            $total = bcmul($amount, $price, 2);
            //买的人扣钱
            $wallet = WalletAccountService::make()->consumption(
                $user_id,
                $total,
                sprintf('求购KC通证,数量:%s,单价%s,共计:%s', $amount, $price, $total),
                6
            );
            if (! $wallet) {
                return [
                    'flag' => false,
                    'msg' => '钱包余额不足!挂售失败',
                ];
            }

            //TODO
            TradingHall::query()->create([
                'user_id' => $user_id,
                'amount' => $amount,
                'price' => $price,
                'type' => 1,
                'status' => 1,
                'traded_quantity' => 0,
            ]);
            return [
                'flag' => true,
                'msg' => '求购单创建成功',
            ];
        });
    }

    private function completed(TradingHall $sellTrading, $buyTrading) //完成交易
    {
        CreditTrade::query()->create([
            'buy_order_id' => $buyTrading->id,
            'sell_order_id' => $sellTrading->id,
            'buyer_id' => $buyTrading->user_id,
            'seller_id' => $sellTrading->user_id,
            'amount' => $buyTrading->amount,
            'price' => $buyTrading->price,
            'total_price' => bcmul($buyTrading->amount, $buyTrading->price, 2),
            'matched_at' => now()->toDateTimeString(),
        ]);
    }
}
